#[[
信号: 使用 kill -l 可查看所有的信号。
liuyou@liuyou-virtual-machine:~/CLionProjects/LinuxEnvironmentProgramming2$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

core文件: 是一个进程的某一个现场, 一般是某一个出错的现场。一个进程的出错现场对程序员来说是非常宝贵的资源之一。

liuyou@liuyou-virtual-machine:~/CLionProjects/LinuxEnvironmentProgramming2$  ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15374
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15374
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

默认是不出现core文件的。core file size          (blocks, -c) 0

我们可以指定产生core文件: 指定可以产生core文件, 并且规定一个core文件最大是10MB。
liuyou@liuyou-virtual-machine:~/CLionProjects/LinuxEnvironmentProgramming2$ ulimit -c 10240
liuyou@liuyou-virtual-machine:~/CLionProjects/LinuxEnvironmentProgramming2$ ulimit -a
core file size          (blocks, -c) 10240
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15374
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15374
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

core文件名一般为: core.pid。出错进程产生的core文件。

在编译源代码的时候加一些编译选项, 例如: 如果加入了 -g 调试选项, 那么就可以使用 gdb 调试这个core文件。
例如:
liuyou@liuyou-virtual-machine:~/CLionProjects/LinuxEnvironmentProgramming2$ gdb core.123845


多半的信号都是终止当前进程或者是终止当前进程+生成core文件。


// signal - ANSI C signal handling
SYNOPSIS
       #include <signal.h>

       typedef void (*sighandler_t)(int);

       // 当 signum 到来了, 就执行 handler 规定的行为。
       // 返回值是 signum 信号之前的行为。
       // handler规定的行为是由 一个函数指定的, 信号处理函数。
       sighandler_t signal(int signum, sighandler_t handler);
       // 即函数是下面这种形式。
       void (*signal(int signum, void (*func)(int)))(int);


DESCRIPTION
       The behavior of signal() varies across UNIX versions, and has also varied historically across different versions of Linux.  Avoid its use: use sigac‐
       tion(2) instead.  See Portability below.
       signal() 的行为因 UNIX 版本而异，并且在历史上也因 Linux 的不同版本而异。
       避免使用它：改用 sigaction(2)。请参阅下面的便携性

       signal() sets the disposition of the signal signum to handler, which is either SIG_IGN, SIG_DFL, or the address of a programmer-defined  function  (a
       "signal handler").
       signal() 将信号 signum 的处置设置为 handler，它可以是 SIG_IGN、SIG_DFL 或程序员定义的函数（“信号处理函数”）的地址。

       If the signal signum is delivered to the process, then one of the following happens:
       如果将信号signum传递给进程，则会发生以下情况之一:

       *  If the disposition is set to SIG_IGN, then the signal is ignored.
       如果处置设置为 SIG_IGN，则忽略该信号。

       *  If the disposition is set to SIG_DFL, then the default action associated with the signal (see signal(7)) occurs.
       如果处置设置为 SIG_DFL，则会发生与信号关联的默认操作（请参阅 signal(7)）。

       *  If  the disposition is set to a function, then first either the disposition is reset to SIG_DFL, or the signal is blocked (see Portability below),
          and then handler is called with argument signum.  If invocation of the handler caused the signal to be blocked, then the signal is unblocked  upon
          return from the handler.
        如果处置设置为函数，则首先将处置重置为 SIG_DFL，或者阻止信号（请参阅下面的可移植性），然后使用参数 signum 调用处理程序。
        如果处理程序的调用导致信号被阻塞，则信号在从处理程序返回时解除阻塞。

       The signals SIGKILL and SIGSTOP cannot be caught or ignored.
       信号 SIGKILL 和 SIGSTOP 不能被捕获或者被忽略。

RETURN VALUE
       signal() returns the previous value of the signal handler, or SIG_ERR on error.  In the event of an error, errno is set to indicate the cause.
       signal() 返回信号处理程序的先前值，或在出错时返回 SIG_ERR。发生错误时，设置 errno 以指示原因。

ERRORS
       EINVAL signum is invalid.
       EINVAL 参数是无效的。

]]
add_executable(Signal-star1 Signal-star1.cpp)
add_executable(Signal-star2 Signal-star2.cpp)
add_executable(Signal-alarm1 Signal-alarm1.cpp)
add_executable(Signal-alarm2 Signal-alarm2.cpp)
add_executable(Signal-5sec Signal-5sec.cpp)
add_executable(Signal-5sec-signal Signal-5sec-signal.cpp)
add_executable(Signal-SlowCat Signal-SlowCat.cpp)
add_executable(Signal-SlowCat2 Signal-SlowCat2.cpp)

# 将 signal/Signal-SlowCat2.cpp 重构成一个现成的库, 为用户提供几个方法。
#[[
对这个库有要求:
1. 用户如果来进行一个程序当中多个不同速率的流控。
2. 指定不同的令牌桶速率。
]]
add_subdirectory(mytbf)
add_subdirectory(alarm)

#[[

使用单一计时器 利用alarm();或者setitimer();实现;, 构造一组函数, 实现任意数量的计时器。
这个和之前写的令牌桶非常的相似。

使用 alarm();  函数时, 如果有
alarm(10);
alarm(1);
alarm(5);
那么只有一个 alarm(); 生效, 那就是 alarm(5); 生效。

]]
add_subdirectory(AnyTimer)
add_subdirectory(AnyTimer2)

add_executable(Signal-setitimer1 Signal-setitimer1.cpp)
add_executable(Signal-abort Signal-abort.cpp)

#[[

信号集

信号集相关操作的函数:

NAME
       sigemptyset, sigfillset, sigaddset, sigdelset, sigismember - POSIX signal set operations.(POSIX 信号集操作。)

SYNOPSIS
       #include <signal.h>

       sigset_t: 这个类型是抽象出来的, 这个类型就是 typedef 出来的一个多少位的整形。
       多少位不重要, 只要能囊括标准信号的个数就可以。相当于一个位图的形式来映射到支持的信号上。

       // 把 一个信号集 set 的内容清空, 即清除一个信号集中的所有信号。
       int sigemptyset(sigset_t *set);

       // 把 一个信号集 set 置为全集, 即这个信号集包含所有的信号。
       int sigfillset(sigset_t *set);

       // 把 signum 信号 添加到 set 信号集中。
       int sigaddset(sigset_t *set, int signum);

       // 从 set 信号集中 删除 signum 信号。
       int sigdelset(sigset_t *set, int signum);

       // 判断 signum 信号 是否在 set信号集 中。
       int sigismember(const sigset_t *set, int signum);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
   glibc 的功能测试宏要求（请参阅 feature_test_macros(7)）:

       sigemptyset(), sigfillset(), sigaddset(), sigdelset(), sigismember():
           _POSIX_C_SOURCE

DESCRIPTION
       These functions allow the manipulation of POSIX signal sets.
       这些函数允许操作 POSIX 信号集。

       sigemptyset() initializes the signal set given by set to empty, with all signals excluded from the set.
       sigemptyset() 将 set 给定的信号集初始化为空，所有信号都从该集合中排除。

       sigfillset() initializes set to full, including all signals.
       sigfillset() 将 set 初始化为 full，包括所有信号。

       sigaddset() and sigdelset() add and delete respectively signal signum from set.
       sigaddset() 和 sigdelset() 分别从集合中添加和删除信号符号。

       sigismember() tests whether signum is a member of set.
       sigismember() 测试 signum 是否是集合的成员。

       Objects  of  type  sigset_t  must  be initialized by a call to either sigemptyset() or sigfillset() before being passed to the functions sigaddset(),
       sigdelset() and sigismember() or the additional glibc functions described below (sigisemptyset(), sigandset(), and sigorset()).  The results are  un‐
       defined if this is not done.
       sigset_t 类型的对象在传递给函数 sigaddset()、sigdelset() 和 sigismember()
       或下面描述的附加 glibc 函数（sigisemptyset()、sigandset() 之前，
       必须通过调用 sigemptyset() 或 sigfillset() 进行初始化) 和 sigorset())。
       如果不这样做，结果是不确定的。

RETURN VALUE
       sigemptyset(), sigfillset(), sigaddset(), and sigdelset() return 0 on success and -1 on error.
       sigemptyset()、sigfillset()、sigaddset() 和 sigdelset() 成功时返回 0，错误时返回 -1。

       sigismember() returns 1 if signum is a member of set, 0 if signum is not a member, and -1 on error.
       sigismember() 如果 signum 是 set 的成员，则返回 1，如果 signum 不是成员，则返回 0，错误时返回 -1。

       On error, these functions set errno to indicate the cause of the error.
       出现错误时，这些函数会设置 errno 以指示错误的原因。

ERRORS
       EINVAL signum is not a valid signal.
       EINVAL 符号不是有效信号。

]]


#[[
信号屏蔽字/pending集的处理

NAME
       sigprocmask, rt_sigprocmask - examine and change blocked signals.(检查和更改阻塞信号。)

SYNOPSIS
       #include <signal.h>

       // sigprocmask();提供了用户可以人为的操作 信号响应过程中的 mask。
       进程收到的信号是反映在 pending位图上, mask位图是当前信号的状态,
       如果把 mask位图设置为0的话, 那么来那个信号当前的进程都看不到, 即忽略。

       使用 sigprocmask(); 可以决定信号什么时候响应。我们不能够决定进程什么时候
       收到信号(即信号什么时候到来), 但是我们能够决定信号什么时候被响应。


       how的操作是针对第二个参数 set的。例如: 我在 set 信号集中放入了三个信号,
       然后我设置 how, 如果 how设置为了 SIG_BLOCK , 那就是将这三个信号的 mask位
       都置为0了。

       sigprocmask();可以决定信号什么时候响应, 但是信号什么时候来是异步事件。

       /* Prototype for the glibc wrapper function */(glibc 包装函数的原型)
       int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

       /* Prototype for the underlying system call */(底层系统调用的原型)
       int rt_sigprocmask(int how, const kernel_sigset_t *set, kernel_sigset_t *oldset,
                            size_t sigsetsize);

       /* Prototype for the legacy system call (deprecated) */(遗留系统调用的原型（已弃用）)
       int sigprocmask(int how, const old_kernel_sigset_t *set,
                       old_kernel_sigset_t *oldset);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       sigprocmask(): _POSIX_C_SOURCE

DESCRIPTION
       sigprocmask()  is  used  to  fetch and/or change the signal mask of the calling thread.  The signal mask is the set of signals whose delivery is cur‐
       rently blocked for the caller (see also signal(7) for more details).
       sigprocmask() 用于获取和/或更改调用线程的信号掩码。
       信号掩码是一组信号，其传递当前被调用者阻止（更多细节参见信号（7））。

       The behavior of the call is dependent on the value of how, as follows.
       调用的行为取决于 how 的值，如下所示。

       SIG_BLOCK
              The set of blocked signals is the union of the current set and the set argument.
              阻塞信号的集合是当前集合和集合参数的并集。

              阻塞信号集中的信号。


       SIG_UNBLOCK
              The signals in set are removed from the current set of blocked signals.  It is permissible to  attempt  to  unblock  a  signal  which  is  not
              blocked.
              集合中的信号从当前的阻塞信号集合中移除。允许尝试解除阻塞未阻塞的信号。

       SIG_SETMASK
              The set of blocked signals is set to the argument set.
              阻塞信号集设置为参数集。

       If oldset is non-NULL, the previous value of the signal mask is stored in oldset.
       If set is NULL, then the signal mask is unchanged (i.e., how is ignored), but the current value of the signal mask is nevertheless returned in oldset
       (if it is not NULL).
       如果 oldset 为非 NULL，则信号掩码的先前值存储在 oldset 中。如果 set 为 NULL，
       则信号掩码不变（即忽略 how ），但仍然在 oldset 中返回信号掩码的当前值（如果它不是 NULL）。

       A set of functions for modifying and inspecting variables of type sigset_t ("signal sets") is described in sigsetops(3).
       sigsetops(3) 中描述了一组用于修改和检查 sigset_t 类型变量（“信号集”）的函数。

       The use of sigprocmask() is unspecified in a multithreaded process; see pthread_sigmask(3).
       在多线程进程中未指定 sigprocmask() 的使用；请参阅 pthread_sigmask(3)。

RETURN VALUE
       sigprocmask() returns 0 on success and -1 on error.  In the event of an error, errno is set to indicate the cause.
       sigprocmask() 成功时返回 0，错误时返回 -1。发生错误时，设置 errno 以指示原因。

]]
add_executable(Signal-sigprocmask Signal-sigprocmask.cpp)
add_executable(Signal-sigprocmask2 Signal-sigprocmask2.cpp)
add_executable(Signal-sigprocmask3 Signal-sigprocmask3.cpp)

#[[

NAME
       sigpending, rt_sigpending - examine pending signals.(检查未决信号(代办的信号们)。)

SYNOPSIS
       #include <signal.h>


       // sigpending(); 是老师唯一不会用的函数, 不是不会用, 而是不知道用在什么环境下。
       系统调用一定要扎内核。
       sigpending();扎内核后, 把进程收到的信号拿出来。

       int sigpending(sigset_t *set);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
   glibc 的功能测试宏要求（请参阅 feature_test_macros(7)）：

       sigpending(): _POSIX_C_SOURCE

DESCRIPTION
       sigpending()  returns the set of signals that are pending for delivery to the calling thread (i.e., the signals which have been raised while blocked).
       The mask of pending signals is returned in set.
       sigpending() 返回等待传递给调用线程的一组信号（即，在阻塞时已引发的信号）。待处理信号的掩码在集合中返回。

RETURN VALUE
       sigpending() returns 0 on success and -1 on error.  In the event of an error, errno is set to indicate the cause.
       sigpending() 成功时返回 0，错误时返回 -1。发生错误时，设置 errno 以指示原因。

]]

# 注意: 不能从信号处理函数中随意的往外跳。

#[[

NAME
       sigsuspend, rt_sigsuspend - wait for a signal.(等待一个信号。)

SYNOPSIS
       #include <signal.h>


       // sigsuspend(); 可以帮助我们做一个信号驱动程序。
       之前有一个函数 pause(); 也是等待一个信号。
       但是在某些情况下, pause();就实现不了了, 必须使用 sigsuspend();。


       int sigsuspend(const sigset_t *mask);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
   glibc 的功能测试宏要求（请参阅 feature_test_macros(7)）:

       sigsuspend(): _POSIX_C_SOURCE

DESCRIPTION
       sigsuspend()  temporarily  replaces the signal mask of the calling thread with the mask given by mask and then suspends the thread until delivery of a
       signal whose action is to invoke a signal handler or to terminate a process.
       sigsuspend() 用 mask 给定的掩码临时替换调用线程的信号掩码，然后挂起线程，直到传递信号，其动作是调用信号处理程序或终止进程。

       If the signal terminates the process, then sigsuspend() does not return.  If the signal is caught, then sigsuspend() returns after the signal  handler
       returns, and the signal mask is restored to the state before the call to sigsuspend().
       如果信号终止进程，则 sigsuspend() 不会返回。
       如果信号被捕获，则在信号处理程序返回后 sigsuspend() 返回，并将信号掩码恢复到调用 sigsuspend() 之前的状态。

       It is not possible to block SIGKILL or SIGSTOP; specifying these signals in mask, has no effect on the thread's signal mask.
       无法阻止 SIGKILL 或 SIGSTOP；在掩码中指定这些信号对线程的信号掩码没有影响。

RETURN VALUE
       sigsuspend() always returns -1, with errno set to indicate the error (normally, EINTR).
       sigsuspend() 始终返回 -1，并设置 errno 以指示错误（通常为 EINTR）。

]]

add_executable(Signal-sigsuspend Signal-sigsuspend.cpp)
add_executable(Signal-sigsuspend2 Signal-sigsuspend2.cpp)
add_executable(Signal-sigsuspend3 Signal-sigsuspend3.cpp)

#[[
NAME
       sigaction, rt_sigaction - examine and change a signal action.(检查和更改信号动作。)

SYNOPSIS
       #include <signal.h>

       // signal();函数是有使用上的缺陷的, 以后只使用 sigaction();函数。

       // signum: 对哪个信号注册信号处理函数。
       // act: 信号的具体行为。
       // 如果对之前的状态不关心, 那么就将 oldact 传入 空指针 nullptr。
       int sigaction(int signum, const struct sigaction *act,
                     struct sigaction *oldact);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
   glibc 的功能测试宏要求（请参阅 feature_test_macros(7)）:

       sigaction(): _POSIX_C_SOURCE

       siginfo_t: _POSIX_C_SOURCE >= 199309L

DESCRIPTION
       The  sigaction()  system call is used to change the action taken by a process on receipt of a specific signal.  (See signal(7) for an overview of signals.)
       sigaction() 系统调用用于更改进程在接收到特定信号时采取的操作。 （有关信号的概述，请参阅信号（7）。）

       signum specifies the signal and can be any valid signal except SIGKILL and SIGSTOP.
       signum 指定信号，可以是除 SIGKILL 和 SIGSTOP 之外的任何有效信号。

       If act is non-NULL, the new action for signal signum is installed from act.  If oldact is non-NULL, the previous action is saved in oldact.
       如果act 为非NULL，则从act 安装信号signum 的新操作。如果 oldact 为非 NULL，则先前的操作将保存在 oldact 中。

       The sigaction structure is defined as something like:
       sigaction 结构定义为:

           struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };

       On some architectures a union is involved: do not assign to both sa_handler and sa_sigaction.
       在某些体系结构上涉及联合：不要同时分配给 sa_handler 和 sa_sigaction。

       The sa_restorer field is not intended for application use.  (POSIX does not specify a sa_restorer field.)  Some further details of the purpose of this
       field can be found in sigreturn(2).
       sa_restorer 字段不适用于应用程序。 （POSIX 没有指定 sa_restorer 字段。）可以在 sigreturn(2) 中找到有关此字段用途的更多详细信息。

       sa_handler specifies the action to be associated with signum and may be SIG_DFL for the default action, SIG_IGN to ignore this signal, or a pointer to
       a signal handling function.  This function receives the signal number as its only argument.
       sa_handler 指定要与 signum 关联的动作，并且可以是 SIG_DFL 表示默认动作，SIG_IGN 表示忽略此信号，或者是指向信号处理函数的指针。此函数接收信号编号作为其唯一参数。

       If SA_SIGINFO is specified in sa_flags, then sa_sigaction (instead of sa_handler) specifies the signal-handling function for  signum.   This  function
       receives three arguments, as described below.
       如果在sa_flags 中指定了SA_SIGINFO，则sa_sigaction（而不是sa_handler）指定signum 的信号处理函数。该函数接收三个参数，如下所述。

       sa_mask specifies a mask of signals which should be blocked (i.e., added to the signal mask of the thread in which the signal handler is invoked) dur‐
       ing execution of the signal handler.  In addition, the signal which triggered the handler will be blocked, unless the SA_NODEFER flag is used.
       sa_mask 指定在信号处理程序执行期间应该被阻塞的信号掩码（即，添加到调用信号处理程序的线程的信号掩码中）。此外，触发处理程序的信号将被阻塞，除非使用 SA_NODEFER 标志。

       sa_flags specifies a set of flags which modify the behavior of the signal.  It is formed by the bitwise OR of zero or more of the following:
       sa_flags 指定一组修改信号行为的标志。它由以下零个或多个的按位或组成:

           SA_NOCLDSTOP
                  If signum is SIGCHLD, do not receive notification when child processes stop (i.e., when they receive one of SIGSTOP, SIGTSTP,  SIGTTIN,  or
                  SIGTTOU) or resume (i.e., they receive SIGCONT) (see wait(2)).  This flag is meaningful only when establishing a handler for SIGCHLD.
                  如果 signum 是 SIGCHLD，则在子进程停止（即，当它们收到 SIGSTOP、SIGTSTP、SIGTTIN 或 SIGTTOU 之一）或恢复（即，它们收到 SIGCONT）时不接收通知（请参阅 wait(2)）。
                  此标志仅在为 SIGCHLD 建立处理程序时才有意义。

           SA_NOCLDWAIT (since Linux 2.6)
                  If  signum is SIGCHLD, do not transform children into zombies when they terminate.  See also waitpid(2).  This flag is meaningful only when
                  establishing a handler for SIGCHLD, or when setting that signal's disposition to SIG_DFL.
                  如果 signum 是 SIGCHLD，则不要在孩子终止时将其转变成僵尸。另请参见 waitpid(2)。此标志仅在为 SIGCHLD 建立处理程序时，或在将该信号的处置设置为 SIG_DFL 时才有意义。

                  If the SA_NOCLDWAIT flag is set when establishing a handler for SIGCHLD, POSIX.1 leaves it unspecified whether a SIGCHLD signal  is  generated
                   when a child process terminates.  On Linux, a SIGCHLD signal is generated in this case; on some other implementations, it is not.
                   如果在为 SIGCHLD 建立处理程序时设置了 SA_NOCLDWAIT 标志，则 POSIX.1 不指定是否在子进程终止时生成 SIGCHLD 信号。
                   在 Linux 上，在这种情况下会生成一个 SIGCHLD 信号；在其他一些实现中，它不是。

           SA_NODEFER
                  Do  not prevent the signal from being received from within its own signal handler.  This flag is meaningful only when establishing a signal
                  handler.  SA_NOMASK is an obsolete, nonstandard synonym for this flag.
                  不要阻止从其自己的信号处理程序中接收信号。此标志仅在建立信号处理程序时才有意义。 SA_NOMASK 是此标志的过时、非标准同义词。

           SA_ONSTACK
                  Call the signal handler on an alternate signal stack provided by sigaltstack(2).  If an alternate stack is not available, the default stack
                  will be used.  This flag is meaningful only when establishing a signal handler.
                  在 sigaltstack(2) 提供的备用信号堆栈上调用信号处理程序。如果备用堆栈不可用，则将使用默认堆栈。此标志仅在建立信号处理程序时才有意义。

           SA_RESETHAND
                  Restore  the  signal  action to the default upon entry to the signal handler.  This flag is meaningful only when establishing a signal han‐
                  dler.  SA_ONESHOT is an obsolete, nonstandard synonym for this flag.
                  在进入信号处理程序时将信号操作恢复为默认值。该标志仅在建立信号处理程序时才有意义。 SA_ONESHOT 是此标志的过时、非标准同义词。

           SA_RESTART
                  Provide behavior compatible with BSD signal semantics by making certain system calls restartable across signals.  This flag  is  meaningful
                  only when establishing a signal handler.  See signal(7) for a discussion of system call restarting.
                  通过使某些系统调用可跨信号重新启动，提供与 BSD 信号语义兼容的行为。此标志仅在建立信号处理程序时才有意义。有关系统调用重新启动的讨论，请参见 signal(7)。

           SA_RESTORER
                  Not  intended for application use.  This flag is used by C libraries to indicate that the sa_restorer field contains the address of a "sig‐
                  nal trampoline".  See sigreturn(2) for more details.
                  不适用于应用程序。 C 库使用此标志来指示 sa_restorer 字段包含“信号蹦床”的地址。有关更多详细信息，请参阅 sigreturn(2)。

           SA_SIGINFO (since Linux 2.2)
                  The signal handler takes three arguments, not one.  In this case, sa_sigaction should be set instead of sa_handler.  This flag is  meaning‐
                  ful only when establishing a signal handler.
                  信号处理程序接受三个参数，而不是一个。在这种情况下，应设置 sa_sigaction 而不是 sa_handler。该标志仅在建立信号处理程序时才有意义。

   The siginfo_t argument to a SA_SIGINFO handler
       When  the SA_SIGINFO flag is specified in act.sa_flags, the signal handler address is passed via the act.sa_sigaction field.  This handler takes three
       arguments, as follows:
       SA_SIGINFO 处理程序的 siginfo_t 参数 当在 act.sa_flags 中指定 SA_SIGINFO 标志时，信号处理程序地址通过 act.sa_sigaction 字段传递。此处理程序采用三个参数，如下所示:

           void
           handler(int sig, siginfo_t *info, void *ucontext)
           {
               ...
           }

       These three arguments are as follows
       这三个参数如下

       sig    The number of the signal that caused invocation of the handler.
       导致调用处理程序的信号数。

       info   A pointer to a siginfo_t, which is a structure containing further information about the signal, as described below.
       指向 siginfo_t 的指针，该结构包含有关信号的更多信息，如下所述。

       ucontext
              This is a pointer to a ucontext_t structure, cast to void *.  The structure pointed to by this field contains signal context  information  that
              was  saved  on  the  user-space  stack by the kernel; for details, see sigreturn(2).  Further information about the ucontext_t structure can be
              found in getcontext(3).  Commonly, the handler function doesn't make any use of the third argument.
              这是一个指向 ucontext_t 结构的指针，转换为 void 。该字段指向的结构包含内核保存在用户空间堆栈上的信号上下文信息；有关详细信息，请参阅 sigreturn(2)。
              有关 ucontext_t 结构的更多信息可以在 getcontext(3) 中找到。通常，处理程序函数不使用第三个参数。

       The siginfo_t data type is a structure with the following fields:
       siginfo_t 数据类型是具有以下字段的结构:

           siginfo_t {
               int      si_signo;     /* Signal number */
               int      si_errno;     /* An errno value */
               int      si_code;      /* Signal code */
               int      si_trapno;    /* Trap number that caused
                                         hardware-generated signal
                                         (unused on most architectures) */
               pid_t    si_pid;       /* Sending process ID */
               uid_t    si_uid;       /* Real user ID of sending process */
               int      si_status;    /* Exit value or signal */
               clock_t  si_utime;     /* User time consumed */
               clock_t  si_stime;     /* System time consumed */
               sigval_t si_value;     /* Signal value */
               int      si_int;       /* POSIX.1b signal */
               void    *si_ptr;       /* POSIX.1b signal */
               int      si_overrun;   /* Timer overrun count;
                                         POSIX.1b timers */
               int      si_timerid;   /* Timer ID; POSIX.1b timers */
               void    *si_addr;      /* Memory location which caused fault */
               long     si_band;      /* Band event (was int in
                                         glibc 2.3.2 and earlier) */
               int      si_fd;        /* File descriptor */
               short    si_addr_lsb;  /* Least significant bit of address
                                         (since Linux 2.6.32) */
               void    *si_lower;     /* Lower bound when address violation
                                         occurred (since Linux 3.19) */
               void    *si_upper;     /* Upper bound when address violation
                                         occurred (since Linux 3.19) */
               int      si_pkey;      /* Protection key on PTE that caused
                                         fault (since Linux 4.6) */
               void    *si_call_addr; /* Address of system call instruction
                                         (since Linux 3.5) */
               int      si_syscall;   /* Number of attempted system call
                                         (since Linux 3.5) */
               unsigned int si_arch;  /* Architecture of attempted system call
                                         (since Linux 3.5) */
           }

       si_signo, si_errno and si_code are defined for all signals.  (si_errno is generally unused on Linux.)  The rest of the struct may be a union, so  that
       one should read only the fields that are meaningful for the given signal:

       * Signals  sent with kill(2) and sigqueue(3) fill in si_pid and si_uid.  In addition, signals sent with sigqueue(3) fill in si_int and si_ptr with the
         values specified by the sender of the signal; see sigqueue(3) for more details.

       * Signals sent by POSIX.1b timers (since Linux 2.6) fill in si_overrun and si_timerid.  The si_timerid field is an internal ID used by the  kernel  to
         identify  the  timer;  it is not the same as the timer ID returned by timer_create(2).  The si_overrun field is the timer overrun count; this is the
         same information as is obtained by a call to timer_getoverrun(2).  These fields are nonstandard Linux extensions.

       * Signals sent for message queue notification (see the description of SIGEV_SIGNAL in mq_notify(3)) fill in si_int/si_ptr, with the  sigev_value  sup‐
         plied to mq_notify(3); si_pid, with the process ID of the message sender; and si_uid, with the real user ID of the message sender.

       * SIGCHLD  fills  in  si_pid, si_uid, si_status, si_utime, and si_stime, providing information about the child.  The si_pid field is the process ID of
         the child; si_uid is the child's real user ID.  The si_status field contains the exit status of the child (if si_code is CLD_EXITED), or the  signal
         number  that  caused  the  process to change state.  The si_utime and si_stime contain the user and system CPU time used by the child process; these
         fields do not include the times used by waited-for children (unlike getrusage(2) and times(2)).  In kernels up  to  2.6,  and  since  2.6.27,  these
         fields  report CPU time in units of sysconf(_SC_CLK_TCK).  In 2.6 kernels before 2.6.27, a bug meant that these fields reported time in units of the
         (configurable) system jiffy (see time(7)).

       * SIGILL, SIGFPE, SIGSEGV, SIGBUS, and SIGTRAP fill in si_addr with the address of the fault.  On some architectures, these signals also fill  in  the
         si_trapno field.

         Some  suberrors  of SIGBUS, in particular BUS_MCEERR_AO and BUS_MCEERR_AR, also fill in si_addr_lsb.  This field indicates the least significant bit
         of the reported address and  therefore  the  extent  of  the  corruption.   For  example,  if  a  full  page  was  corrupted,  si_addr_lsb  contains
         log2(sysconf(_SC_PAGESIZE)).   When  SIGTRAP  is delivered in response to a ptrace(2) event (PTRACE_EVENT_foo), si_addr is not populated, but si_pid
         and si_uid are populated with the respective process ID and user ID responsible for delivering the trap.  In the case of seccomp(2), the tracee will
         be shown as delivering the event.  BUS_MCEERR_* and si_addr_lsb are Linux-specific extensions.

         The SEGV_BNDERR suberror of SIGSEGV populates si_lower and si_upper.

         The SEGV_PKUERR suberror of SIGSEGV populates si_pkey.

       * SIGIO/SIGPOLL  (the  two names are synonyms on Linux) fills in si_band and si_fd.  The si_band event is a bit mask containing the same values as are
         filled in the revents field by poll(2).  The si_fd field indicates the file descriptor for which the I/O event occurred; for  further  details,  see
         the description of F_SETSIG in fcntl(2).

       * SIGSYS,  generated (since Linux 3.5) when a seccomp filter returns SECCOMP_RET_TRAP, fills in si_call_addr, si_syscall, si_arch, si_errno, and other
         fields as described in seccomp(2).

   The si_code field
       The si_code field inside the siginfo_t argument that is passed to a SA_SIGINFO signal handler is a value (not a bit mask) indicating why  this  signal
       was sent.  For a ptrace(2) event, si_code will contain SIGTRAP and have the ptrace event in the high byte:

           (SIGTRAP | PTRACE_EVENT_foo << 8).

       For a non-ptrace(2) event, the values that can appear in si_code are described in the remainder of this section.  Since glibc 2.20, the definitions of
       most of these symbols are obtained from <signal.h> by defining feature test macros (before including any header file) as follows:

       *  _XOPEN_SOURCE with the value 500 or greater;

       *  _XOPEN_SOURCE and _XOPEN_SOURCE_EXTENDED; or

       *  _POSIX_C_SOURCE with the value 200809L or greater.

       For the TRAP_* constants, the symbol definitions are provided only in the first two cases.  Before glibc 2.20, no feature test macros were required to
       obtain these symbols.

       For  a  regular  signal,  the following list shows the values which can be placed in si_code for any signal, along with the reason that the signal was
       generated.

           SI_USER
                  kill(2).

           SI_KERNEL
                  Sent by the kernel.

           SI_QUEUE
                  sigqueue(3).

           SI_TIMER
                  POSIX timer expired.

           SI_MESGQ (since Linux 2.6.6)
                  POSIX message queue state changed; see mq_notify(3).

           SI_ASYNCIO
                  AIO completed.

           SI_SIGIO
                  Queued SIGIO (only in kernels up to Linux 2.2; from Linux 2.4 onward SIGIO/SIGPOLL fills in si_code as described below).

           SI_TKILL (since Linux 2.4.19)
                  tkill(2) or tgkill(2).

       The following values can be placed in si_code for a SIGILL signal:

           ILL_ILLOPC
                  Illegal opcode.

           ILL_ILLOPN
                  Illegal operand.

           ILL_ILLADR
                  Illegal addressing mode.

           ILL_ILLTRP
                  Illegal trap.

           ILL_PRVOPC
                  Privileged opcode.

           ILL_PRVREG
                  Privileged register.

           ILL_COPROC
                  Coprocessor error.

           ILL_BADSTK
                  Internal stack error.

       The following values can be placed in si_code for a SIGFPE signal:

           FPE_INTDIV
                  Integer divide by zero.

           FPE_INTOVF
                  Integer overflow.

           FPE_FLTDIV
                  Floating-point divide by zero.

           FPE_FLTOVF
                  Floating-point overflow.

           FPE_FLTUND
                  Floating-point underflow.

           FPE_FLTRES
                  Floating-point inexact result.

           FPE_FLTINV
                  Floating-point invalid operation.

           FPE_FLTSUB
                  Subscript out of range.

       The following values can be placed in si_code for a SIGSEGV signal:

           SEGV_MAPERR
                  Address not mapped to object.

           SEGV_ACCERR
                  Invalid permissions for mapped object.

           SEGV_BNDERR (since Linux 3.19)
                  Failed address bound checks.

           SEGV_PKUERR (since Linux 4.6)
                  Access was denied by memory protection keys.  See pkeys(7).  The protection key which applied to this access is available via si_pkey.

       The following values can be placed in si_code for a SIGBUS signal:

           BUS_ADRALN
                  Invalid address alignment.

           BUS_ADRERR
                  Nonexistent physical address.

           BUS_OBJERR
                  Object-specific hardware error.

           BUS_MCEERR_AR (since Linux 2.6.32)
                  Hardware memory error consumed on a machine check; action required.

           BUS_MCEERR_AO (since Linux 2.6.32)
                  Hardware memory error detected in process but not consumed; action optional.

       The following values can be placed in si_code for a SIGTRAP signal:

           TRAP_BRKPT
                  Process breakpoint.

           TRAP_TRACE
                  Process trace trap.

           TRAP_BRANCH (since Linux 2.4, IA64 only))
                  Process taken branch trap.

           TRAP_HWBKPT (since Linux 2.4, IA64 only))
                  Hardware breakpoint/watchpoint.

       The following values can be placed in si_code for a SIGCHLD signal:

           CLD_EXITED
                  Child has exited.

           CLD_KILLED
                  Child was killed.

           CLD_DUMPED
                  Child terminated abnormally.

           CLD_TRAPPED
                  Traced child has trapped.

           CLD_STOPPED
                  Child has stopped.

           CLD_CONTINUED (since Linux 2.6.9)
                  Stopped child has continued.

       The following values can be placed in si_code for a SIGIO/SIGPOLL signal:

           POLL_IN
                  Data input available.

           POLL_OUT
                  Output buffers available.

           POLL_MSG
                  Input message available.

           POLL_ERR
                  I/O error.

           POLL_PRI
                  High priority input available.

           POLL_HUP
                  Device disconnected.

       The following value can be placed in si_code for a SIGSYS signal:

           SYS_SECCOMP (since Linux 3.5)
                  Triggered by a seccomp(2) filter rule.

RETURN VALUE
       sigaction() returns 0 on success; on error, -1 is returned, and errno is set to indicate the error.

]]

# 使用 sigaction(); 重构 setitimer1。
add_executable(Signal-sigaction-setitimer1 Signal-sigaction-setitimer1.cpp)

# 使用 sigaction(); 重构令牌桶。
add_subdirectory(mytbf2)

#[[
使用 sigaction(); 和 setitimer(); 来替换掉 signal(); 和 alarm(); 函数。

]]


#[[
标准信号:
    * 标准信号会丢失。因为它是用位图来记录的。
    * 标准信号的响应没有一个严格的顺序。但是大概有一个层次。优先响应造成段错误的信号。

实时信号:
    * 实时信号是需要排队的。
    * 实时信号的响应是有一个顺序的要求。

如果一个进程当中即受到了标准信号又收到了实时信号, 那么先响应标准信号再去响应实时信号。
查看所有信号: kill -l

标准信号中有两个信号是预留给用户来使用的, SIGUSR1 和 SIGUSR2 。用户可以使用这两个信号来做一些内容。

]]
add_executable(Signal-RealTimeSignal Signal-RealTimeSignal.cpp)
#[[
使用 ulimit -a
可查看实时信号最多有多少个。

liuyou@liuyou-virtual-machine:~/CLionProjects/LinuxEnvironmentProgramming2$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
# 在这里: 实时信号能排 15374 个。
pending signals                 (-i) 15374
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15374
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
liuyou@liuyou-virtual-machine:~/CLionProjects/LinuxEnvironmentProgramming2$

]]

#[[

信号部分总结:

信号来完成并发, 主要是在多进程之间进行控制(通过 kill(); )。因为还没有到进程间通信。

信号处理函数不要写的特别长, 如果写的特别长的话, CPU执行的时间也就长了, 所以,
一般是在信号处理函数中设置标志位或者在信号处理函数中写管道, 将信号写进管道。
而信号处理函数的逻辑放在main函数中, 在main函数的某个地方读管道, 根据读到的信号
执行相关的处理。

]]






























































































































